package com.mcflywzx.airhockey.util;

import static android.opengl.Matrix.*;
import com.mcflywzx.airhockey.objects.*;
import static com.mcflywzx.airhockey.util.Geometry.*;

public class MatrixHelper {
	
	private final float[] viewMatrix = new float[16];
	public final float[] viewProjectionMatrix = new float[16];
	public final float[] modelViewProjectionMatrix = new float[16];

	private final float[] invertedViewProjectionMatrix = new float[16];

	private final float[] projectionMatrix = new float[16];
	private final float[] modelMatrix = new float[16];
	int width, height;
	
	public static void perspectiveM(float[] m, float yFovInDegrees, float aspect, float n, float f) {
		//计算焦距
		final float angleInRadians = (float) (yFovInDegrees * Math.PI / 180.0);
		
		final float a = (float) (1.0 / Math.tan(angleInRadians / 2.0));
		//output matrix
		m[0] = a / aspect;
		m[1] = 0f;
		m[2] = 0f;
		m[3] = 0f;
		
		m[4] = 0f;
		m[5] = a;
		m[6] = 0f;
		m[7] = 0f;
		
		m[8] = 0f;
		m[9] = 0f;
		m[10] = -((f + n) / (f - n));
		m[11] = -1f;
		
		m[12] = 0f;
		m[13] = 0f;
		m[14] =  -((2f * f * n) / (f - n));
		m[15] = 0f;
	}
	
	public void initializeCameraMatrix(int width, int height) {
		this.width = width;
		this.height = height;
		MatrixHelper.perspectiveM(projectionMatrix, 50, (float) width / (float) height, 1f, 10f);

		setLookAtM(viewMatrix, 0, 0f, 1f, 3.5f, 0f, 0f, 0f, 0f, 1f, 0f);
	}
	
	public void setCamera(Point p) {
		//MatrixHelper.perspectiveM(projectionMatrix, 50, (float) width / (float) height, 1f, 10f);
		setLookAtM(viewMatrix, 0, p.x, p.y, p.z, p.x, 0f, 0f, 0f, 1f, 0f);
	}
	
	public void initializeScene() {
		multiplyMM(viewProjectionMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
		invertM(invertedViewProjectionMatrix, 0, viewProjectionMatrix, 0);
	}
	
	public void PositionAndRotateObjectInScene(float a, float x, float y, float z) {
		setIdentityM(modelMatrix, 0);
		rotateM(modelMatrix, 0, a, x, y, z);
		multiplyMM(modelViewProjectionMatrix, 0, viewProjectionMatrix, 0, modelMatrix, 0);
	}

	public void PositionAndRotateObjectInScene(float mx, float my, float mz) {
		setIdentityM(modelMatrix, 0);
		translateM(modelMatrix, 0, mx, my, mz);
		multiplyMM(modelViewProjectionMatrix, 0, viewProjectionMatrix, 0, modelMatrix, 0);
	}

	public void PositionAndRotateObjectInScene(float a, float rx, float ry, float rz, float mx, float my, float mz) {
		setIdentityM(modelMatrix, 0);
		translateM(modelMatrix, 0, mx, my, mz);
		rotateM(modelMatrix, 0, a, rx, ry, rz);
		multiplyMM(modelViewProjectionMatrix, 0, viewProjectionMatrix, 0, modelMatrix, 0);
	}
	
	public void PositionAndRotateCubeInScene(MCube Mc) {
		for(int i = 0; i < Mc.s.length; i++) {
			setIdentityM(modelMatrix, 0);
			translateM(modelMatrix, 0, Mc.position.x, Mc.position.y, Mc.position.z);
			
			//rotateM(modelMatrix, 0, 180, 1, 0, 0);
			//rotateM(modelMatrix, 0, a, 0, 1, 0);
			
			switch(i) {
				case 0 : 
					translateM(modelMatrix, 0, 0f, -Mc.H/2, 0f);
					multiplyMM(modelViewProjectionMatrix, 0, viewProjectionMatrix, 0, modelMatrix, 0);
					Mc.s[0].draw(modelViewProjectionMatrix);
					break;
				case 1 :
					translateM(modelMatrix, 0, 0f, Mc.H/2, 0f);
					rotateM(modelMatrix, 0, 180f, 1f, 0f, 0f);
					multiplyMM(modelViewProjectionMatrix, 0, viewProjectionMatrix, 0, modelMatrix, 0);
					Mc.s[1].draw(modelViewProjectionMatrix);
					break;
				case 2 :
					translateM(modelMatrix, 0, -Mc.W/2, 0f, 0f);
					rotateM(modelMatrix, 0, 90f, 0f, 0f, 1f);
					rotateM(modelMatrix, 0, -90f, 0f, 1f, 0f);
					rotateM(modelMatrix, 0, 180f, 1f, 0f, 0f);
					multiplyMM(modelViewProjectionMatrix, 0, viewProjectionMatrix, 0, modelMatrix, 0);
					Mc.s[2].draw(modelViewProjectionMatrix);
					break;
				case 3 :
					translateM(modelMatrix, 0, Mc.W/2, 0f, 0f);
					rotateM(modelMatrix, 0, 90f, 0f, 0f, 1f);
					rotateM(modelMatrix, 0, 90f, 0f, 1f, 0f);
					multiplyMM(modelViewProjectionMatrix, 0, viewProjectionMatrix, 0, modelMatrix, 0);
					Mc.s[3].draw(modelViewProjectionMatrix);
					break;
				case 4 :
					translateM(modelMatrix, 0, 0, 0f, Mc.L/2);
					rotateM(modelMatrix, 0, 90f, 1f, 0f, 0f);
					rotateM(modelMatrix, 0, 180f, 1f, 0f, 0f);
					multiplyMM(modelViewProjectionMatrix, 0, viewProjectionMatrix, 0, modelMatrix, 0);
					Mc.s[4].draw(modelViewProjectionMatrix);
					break;
				case 5 :
					translateM(modelMatrix, 0, 0, 0f, -Mc.L/2);
					rotateM(modelMatrix, 0, 90f, 1f, 0f, 0f);
					rotateM(modelMatrix, 0, 180f, 0f, 1f, 0f);
					multiplyMM(modelViewProjectionMatrix, 0, viewProjectionMatrix, 0, modelMatrix, 0);
					Mc.s[4].draw(modelViewProjectionMatrix);
					break;
			}
		}
		
		
	}
}
